package com.example.demo.heartbeat;

import cn.hutool.core.util.StrUtil;
import com.example.demo.entity.ClientServerRequest;
import com.example.demo.util.SpringContextUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;

@Slf4j
public class HeartBeatSimpleHandle extends SimpleChannelInboundHandler<HeartBeat> {

    private static final ByteBuf HEART_BEAT = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer(new HeartBeat(123456L, "pong", "", "").toString(), CharsetUtil.UTF_8));

    /**
     * 取消绑定
     * 客户端主动关闭只会触发此方法 不会触发userEventTriggered
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("客户端下线取消绑定");
        InetSocketAddress inSocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String str = NettySocketHolder.get((NioSocketChannel) ctx.channel());
        if (StrUtil.isNotBlank(str)) {
            String[] param = str.split("-");
            ClientServerRequest request = new ClientServerRequest();
            request.setWhId(Long.parseLong(param[0]));
            request.setClientName(param[2]);
            request.setClientIp(param[1]);
            // 收到客户端下线后，取消绑定时，可进行业务处理
            // 我们采用的是记录客户端服务的状态到数据库，通过钉钉机器人进行告警信息通知
            // BusinessService businessService = SpringContextUtil.getBean(BusinessService.class);
            // businessService.offline(request);
        }
        NettySocketHolder.remove((NioSocketChannel) ctx.channel());
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            if (idleStateEvent.state() == IdleState.READER_IDLE) {
                log.info("已经5秒没有收到信息!清空心跳");
                //向客户端发送消息
                ctx.writeAndFlush(HEART_BEAT).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            }
        }
        super.userEventTriggered(ctx, evt);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HeartBeat heartBeat) throws Exception {
        InetSocketAddress inSocket = (InetSocketAddress) ctx.channel().remoteAddress();
        log.info("收到来自主机[{}][{}]的心跳", heartBeat.getHostName(), heartBeat.getHostAddress());
        //组装客户端数据
        ClientServerRequest request = new ClientServerRequest();
        request.setWhId(heartBeat.getBusinessId());
        request.setClientName(heartBeat.getHostName());
        request.setClientIp(heartBeat.getHostAddress());
        request.setClientVersion(heartBeat.getClientVersion());
        // 处理业务数据,记录收到客户端心跳后的操作，服务端采取的措施
//        BusinessService businessService = SpringContextUtil.getBean(BusinessService.class);
//        businessService.handle(request);
        //保存客户端与 Channel 之间的关系
        NettySocketHolder.put(heartBeat.getBusinessId() + "-" + heartBeat.getHostAddress() + "-" + heartBeat.getHostName(),
                (NioSocketChannel) ctx.channel());
    }


    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
    }


}

